--[[
	Copyright (C) Udorn (Blackhand)
--]]

lootlog = lootlog or {}

lootlog.LootLog = LibStub("AceAddon-3.0"):NewAddon("Lootlog", "AceEvent-3.0", "AceConsole-3.0", "AceHook-3.0")
local L = lootlog.Locale.GetInstance()
local log = lootlog.Debug:new("Lootlog")

local AceConfigDialog = LibStub("AceConfigDialog-3.0")

local APP_NAME = "Lootlog"

local order = 1

local SCREEN_HEIGHT = GetScreenHeight()
local SCREEN_WIDTH = GetScreenWidth()

local PLAYER = 1
local ITEM = 2
local DICE = 3

local function _NextOrder()
	order = order + 1
	return order
end

local DEFAULT_CONFIG = {
	profile = {
		backgroundColor = {0.282, 0.239, 0.541, 0.62},
		lostBackgroundColor = {0.976, 0.114, 0.112, 1},
		lostNeedOnly = true,
		wonBackgroundColor = {0.31, 0.91, 0.216, 1},
		wonNeedOnly = true,
		fadeoutTime = 30,
		showClass = false,
		colorizePlayerName = true,
		scale = 1,
		minQuality = 2,
		activeGroup = true,
		activeRaid10 = true,
		activeRaid25 = true,
		activeRaid40 = true,
		windowPosition = {
			point = "TOPLEFT",
			relativePoint = "TOPLEFT", 
			x = SCREEN_WIDTH / 15, 
			y = -(SCREEN_HEIGHT / 3)
		}
	}
}

local OPTIONS = {
	--name = APP_NAME,
	handler = lootlog.LootLog,
	type = 'group',
	childGroups = "tab",
	args = {
		locked = {
			type = 'toggle',
			width = "half",
			name = L["Locked"],
			desc = L["Locks the window"],
			order = _NextOrder(),
			set = function(info, value) info.handler.db.profile.locked = value; end,
			get = function(info) return info.handler.db.profile.locked end,
		},
		test = {
			type = 'toggle',
			name = L["Test"],
			desc = L["Activates the test mode for moving the window and modifying the layout"],
			order = _NextOrder(),
			set = function(info, value) info.handler.db.profile.testMode = value; info.handler.lootWindow:TestModeUpdate() end,
			get = function(info) return info.handler.db.profile.testMode end,
		},
	 	main = {
		 	type="group",
		 	name = L["View"],
		 	order = _NextOrder(),
		 	args = {
				fadeoutTime = {
					type = 'range',
					name = L["Fadeout time"],
					desc = L["Number of seconds an item is still visible after it has been won"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.fadeoutTime = value end,
					get = function(info) return info.handler.db.profile.fadeoutTime end,
					min = 1,
					max = 60,
					step = 1,
				},
				scale = {
					type = 'range',
					name = L["Scale"],
					desc = L["Scale factor of the Lootlog window"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.scale = value end,
					get = function(info) return info.handler.db.profile.scale end,
					min = 0.1,
					max = 3,
					step = 0.01,
				},
				newLine1 = {
					type = 'description',
					name = "\n",
					order = _NextOrder(),
				},
				showClass = {
					type = 'toggle',
					name = L["Show class"],
					desc = L["Adds the class to the player name"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.showClass = value end,
					get = function(info) return info.handler.db.profile.showClass end,
				},
				colorizePlayerName = {
					type = 'toggle',
					name = L["Class colorization"],
					desc = L["Colorize the player names by their class"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.colorizePlayerName = value end,
					get = function(info) return info.handler.db.profile.colorizePlayerName end,
				},
				newLine2 = {
					type = 'description',
					name = "\n",
					order = _NextOrder(),
				},
				minQuality = {
					type = "select",
					name = L["Minimum quality"],
					desc = L["Only show rolls for items with at least the selected quality"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.minQuality = value; info.handler:Update() end,
					get = function(info) return info.handler.db.profile.minQuality end,
					values = {[0] = ITEM_QUALITY0_DESC, [1] = ITEM_QUALITY1_DESC, [2] = ITEM_QUALITY2_DESC, [3] = ITEM_QUALITY3_DESC, [4] = ITEM_QUALITY4_DESC, [5] = ITEM_QUALITY5_DESC}
				},
				newLine3 = {
					type = 'description',
					name = "\n",
					order = _NextOrder(),
				},
				wonBackgroundColor = {
					type = 'color',
					name = L["Win Background"],
					desc = L["Background color for rolls won"],
					order = _NextOrder(),
					set = function(info, ...) info.handler.db.profile.wonBackgroundColor = {...}; end,
					get = function(info) return unpack(info.handler.db.profile.wonBackgroundColor) end,
					hasAlpha = true
				},
				wonNeedOnly = {
					type = 'toggle',
					name = L["Need only"],
					desc = L["Uses the given background color only for need rolls"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.wonNeedOnly = value end,
					get = function(info) return info.handler.db.profile.wonNeedOnly end,
				},
				lostNewLine = {
					type = 'description',
					name = "",
					order = _NextOrder(),
				},
				lostBackgroundColor = {
					type = 'color',
					name = L["Loss Background"],
					desc = L["Background color for rolls lost"],
					order = _NextOrder(),
					set = function(info, ...) info.handler.db.profile.lostBackgroundColor = {...}; end,
					get = function(info) return unpack(info.handler.db.profile.lostBackgroundColor) end,
					hasAlpha = true
				},
				lostNeedOnly = {
					type = 'toggle',
					name = L["Need only"],
					desc = L["Uses the given background color only for need rolls"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.lostNeedOnly = value end,
					get = function(info) return info.handler.db.profile.lostNeedOnly end,
				},
				backgroundColorNewLine = {
					type = 'description',
					name = "",
					order = _NextOrder(),
				},
				backgroundColor = {
					type = 'color',
					name = L["Background"],
					desc = L["General background color"],
					order = _NextOrder(),
					set = function(info, ...) info.handler.db.profile.backgroundColor = {...}; end,
					get = function(info) return unpack(info.handler.db.profile.backgroundColor) end,
					hasAlpha = true
				},
				activeDesc = {
					type = 'header',
					name = L["Activation"],
					desc = L["Selects the instance types for using Lootlog"],
					order = _NextOrder(),
				},
				activeGroup = {
					type = 'toggle',
					name = L["Group"],
					desc = L["Uses Lootlog in groups"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.activeGroup = value end,
					get = function(info) return info.handler.db.profile.activeGroup end,
				},
				activeRaid10 = {
					type = 'toggle',
					name = L["Raid 10"],
					desc = L["Uses Lootlog in raids of 10 people"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.activeRaid10 = value end,
					get = function(info) return info.handler.db.profile.activeRaid10 end,
				},
				activeRaid25 = {
					type = 'toggle',
					name = L["Raid 25"],
					desc = L["Uses Lootlog in raids of 25 people"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.activeRaid25 = value end,
					get = function(info) return info.handler.db.profile.activeRaid25 end,
				},
				activeRaid40 = {
					type = 'toggle',
					name = L["Raid 40"],
					desc = L["Uses Lootlog in raids of 40 people"],
					order = _NextOrder(),
					set = function(info, value) info.handler.db.profile.activeRaid40 = value end,
					get = function(info) return info.handler.db.profile.activeRaid40 end,
				},
			}
		}
	}
}

local function _IsActive(self)
	local name, type, difficultyIndex, difficultyName, maxPlayers, dynamicDifficulty, isDynamic = GetInstanceInfo()
	local rtn = false
	if (self.db.profile.activeGroup and type == "party") then
		rtn = true
	elseif (type == "raid") then
		rtn = (self.db.profile.activeRaid10 and maxPlayers <= 10) or 
			(self.db.profile.activeRaid25 and maxPlayers > 10 and maxPlayers <= 25) or 
			(self.db.profile.activeRaid40 and maxPlayers > 25)
	end
	log:Debug("IsActive rtn [%s] name [%s] type [%s] difficultyIndex [%s] difficultyName [%s] maxPlayers [%s] dynamicDifficulty [%s] isDynamic [%s]", rtn, name, type, difficultyIndex, difficultyName, maxPlayers, dynamicDifficulty, isDynamic)
	return rtn
end

local function _AddEntry(self, rollType, dice, playerName, itemLink, isWinner)

	if (not itemLink) then return end
	
	local itemName = GetItemInfo(itemLink)
	if (not itemName) then return end
		
	self.lootWindow:SetRoll(rollType, dice, itemName, playerName)
	if (isWinner) then
		self.lootWindow:SetWinner(itemName, playerName)
	end
end

local function _UpdatePlayer(self, playerIdx, itemIdx)
	if (LootHistoryFrameUtil_ShouldDisplayPlayer(itemIdx, playerIdx)) then
		local rollID, itemLink, numPlayers, isDone, winnerIdx = C_LootHistory.GetItem(itemIdx)
		local playerName, class, rollType, roll, isWinner = C_LootHistory.GetPlayerInfo(itemIdx, playerIdx)
		if (playerName) then
			if (rollType == LOOT_ROLL_TYPE_NEED) then
				_AddEntry(self, lootlog.LootWindow.NEED, roll, playerName, itemLink, isWinner)
			elseif (rollType == LOOT_ROLL_TYPE_GREED) then
				_AddEntry(self, lootlog.LootWindow.GREED, roll, playerName, itemLink, isWinner)
			elseif (rollType == LOOT_ROLL_TYPE_DISENCHANT) then
				_AddEntry(self, lootlog.LootWindow.DISENCHANT, roll, playerName, itemLink, isWinner)
			elseif (rollType == LOOT_ROLL_TYPE_PASS) then
				_AddEntry(self, lootlog.LootWindow.PASSED, roll, playerName, itemLink, isWinner)
			end						
		end
	end
end

local function _FullUpdate(self)
	local numItems = C_LootHistory.GetNumItems()
	for itemIdx=1, numItems do
		local rollID, itemLink, numPlayers, isDone, winnerIdx = C_LootHistory.GetItem(itemIdx)
		if (not isDone or winnerIdx or isMasterLoot ) then
			for playerIdx=1, numPlayers do
				_UpdatePlayer(self, playerIdx, itemIdx)
			end
		else
			-- all players passed
			local rollID, itemLink, numPlayers, isDone, winnerIdx = C_LootHistory.GetItem(itemIdx)
			if (not itemLink) then return end
			local itemName = GetItemInfo(itemLink)
			if (not itemName) then return end
			self.lootWindow:SetWinner(itemName, nil)
		end
	end
end

function lootlog.LootLog:OnInitialize()
	self.db = LibStub("AceDB-3.0"):New("LootLogDb", DEFAULT_CONFIG, "Default")
	OPTIONS.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
	self.db.profile.testMode = nil -- just in case
	
	self.db.RegisterCallback(self, "OnProfileChanged", "ProfileUpdate")
	self.db.RegisterCallback(self, "OnProfileCopied", "ProfileUpdate")
	self.db.RegisterCallback(self, "OnProfileReset", "ProfileUpdate")
end

function lootlog.LootLog:OnEnable()
	log:ClearHistory()
	self.lootWindow = lootlog.LootWindow:new()
	self.playerName = GetUnitName("player")
	
	LibStub("AceConfig-3.0"):RegisterOptionsTable(APP_NAME, OPTIONS)
	self.configFrame = AceConfigDialog:AddToBlizOptions(APP_NAME)
	self:RegisterChatCommand("lootlog", "ChatCommand")
		
	self:RegisterEvent("START_LOOT_ROLL")
	self:RegisterEvent("LOOT_HISTORY_FULL_UPDATE");
	self:RegisterEvent("LOOT_HISTORY_ROLL_COMPLETE");
	self:RegisterEvent("LOOT_HISTORY_ROLL_CHANGED");
end

function lootlog.LootLog:LOOT_HISTORY_FULL_UPDATE(evt, msg, id)
	_FullUpdate(self)
end

function lootlog.LootLog:LOOT_HISTORY_ROLL_COMPLETE(evt, msg, id)
	_FullUpdate(self)
end

function lootlog.LootLog:LOOT_HISTORY_ROLL_CHANGED(evt, itemIdx, playerIdx)
	_UpdatePlayer(self, playerIdx, itemIdx)
end

function lootlog.LootLog:ProfileUpdate(event)
	log:Debug("ProfileUpdate event [%s]", event)
	self.lootWindow:ProfileUpdate()
end

function lootlog.LootLog:Update()
	self.lootWindow:TestModeUpdate()
end


function lootlog.LootLog:ChatCommand(msg)
	log:Debug("msg [%s]", msg)
	if ("debug" == msg) then
		if (log:IsDebugging()) then
			print("Turning off debugging")
			log:SetDebugging(nil)
		else
			print("Turning on debugging")
			log:SetDebugging(true)
		end
	elseif ("history" == msg) then
		print("Printing history")
		log:PrintHistory()
	elseif ("clear" == msg) then
		print("Clearing history")
		log:ClearHistory()
	else
		InterfaceOptionsFrame_OpenToCategory(self.configFrame)
	end
end

function lootlog.LootLog:START_LOOT_ROLL(evt, rollId, rollTime)
	log:Debug("START_LOOT_ROLL rollId [%s] rollTime [%s]", rollId, rollTime)
	
	if (not _IsActive(self)) then
		return
	end
	
	local texture, name, count, quality = GetLootRollItemInfo(rollId)
	local itemLink = GetLootRollItemLink(rollId)
	if (name and itemLink and quality >= self.db.profile.minQuality) then
		log:Debug("name [%s] quality [%s]", name, quality)
		self.lootWindow:AddRoll(rollId, name, itemLink, quality)
	end
end

function lootlog.LootLog.Print(self, msg)
	print("|cFF3DDEFF"..msg.."|r")
end
